/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.jfonia.notation;

import org.jfonia.constants.SymbolConstants;
import org.jfonia.constants.ViewConstants;

/**
 *
 * @author Rik Bauwens
 */
public class MusicalTime
{
        public static int toMusicalTime(NoteOrRest noteOrRest)
        {
                return noteOrRest instanceof Note ?
                    toMusicalTime((Note) noteOrRest)
                    : toMusicalTime((Rest) noteOrRest);
        }
        private static int toMusicalTime(Note note)
        {
                int musicalTime = 0;
                if(note.getNoteHead() == ViewConstants.NOTEHEAD1)
                        musicalTime = SymbolConstants.NOTEHEAD_SEMIBREVE;
                else if(note.getNoteHead() == ViewConstants.NOTEHEAD1_2)
                        musicalTime = SymbolConstants.NOTEHEAD_MINIM;
                else
                {
                        musicalTime = SymbolConstants.NOTEHEAD_CROTCHET;
                        for(int i = 0; i < note.getFlags(); i++)
                                musicalTime /= 2;
                }
                for(int i = 0; i < note.getDots(); i++)
                        musicalTime += (musicalTime / 2);
                return musicalTime;
        }

        private static int toMusicalTime(Rest rest)
        {
                int musicalTime = rest.getRest();
                for(int i = 0; i < rest.getDots(); i++)
                        musicalTime += (musicalTime / 2);
                return musicalTime;
        }

        public static Note toNote(int musicalTime)
        {
                if(musicalTime <= 0)
                        return null;
                int musicalTimeLeft = musicalTime;
                int noteHead = 0;
                int flags = 0;
                if(musicalTimeLeft >= SymbolConstants.NOTEHEAD_SEMIBREVE)
                {
                        noteHead = ViewConstants.NOTEHEAD1;
                        musicalTimeLeft -= SymbolConstants.NOTEHEAD_SEMIBREVE;
                }
                else if(musicalTimeLeft < SymbolConstants.NOTEHEAD_SEMIBREVE
                        && musicalTime >= SymbolConstants.NOTEHEAD_MINIM)
                {
                        noteHead = ViewConstants.NOTEHEAD1_2;
                        musicalTimeLeft -= SymbolConstants.NOTEHEAD_MINIM;
                }
                else if(musicalTimeLeft <= SymbolConstants.NOTEHEAD_CROTCHET)
                {
                        noteHead = ViewConstants.NOTEHEAD1_4;;
                        while(musicalTimeLeft / (SymbolConstants.NOTEHEAD_CROTCHET / Math.pow(2, flags)) != 1)
                                flags++;
                        musicalTimeLeft -= SymbolConstants.NOTEHEAD_CROTCHET / Math.pow(2, flags);
                }
                int dots = 0;
                int currentDuration = musicalTime - musicalTimeLeft;
                int stem = currentDuration;
                while(musicalTimeLeft > 0)
                {
                        musicalTimeLeft -= (currentDuration / 2);
                        currentDuration += (currentDuration / 2);
                        dots++;
                }
                return new Note(noteHead, stem, flags, dots);
        }

        public static Rest toRest(int musicalTime)
        {
                if(musicalTime == 0)
                        return null;
                int musicalTimeLeft = musicalTime;
                int rest = ViewConstants.REST1;
                while(musicalTimeLeft == musicalTime)
                {
                        if(musicalTimeLeft / rest == 1)
                                musicalTimeLeft -= rest;
                        rest /= 2;
                }
                int dots = 0;
                int currentDuration = musicalTime - musicalTimeLeft;
                while(musicalTimeLeft > 0)
                {
                        musicalTimeLeft -= (currentDuration / 2);
                        currentDuration += (currentDuration / 2);
                        dots++;
                }
                return new Rest(rest, dots);
        }
}
